package com.lujianfei.filesend.base

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableList
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView

abstract class BaseBindingAdapter<M, B : ViewDataBinding>(private var items: ObservableArrayList<M>) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){

    class BaseBindingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    private val dataListChangedCallback = ListChangedCallback()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val binding: B = DataBindingUtil.inflate(LayoutInflater.from(parent.context), getLayoutResId(), parent, false)
        return BaseBindingViewHolder(binding.root)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is BaseBindingViewHolder) {
            val bean : M = items[position]
            val binding: B? = DataBindingUtil.getBinding(holder.itemView)
            onBindItem(binding, bean, position)
            binding?.executePendingBindings()
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        items.addOnListChangedCallback(dataListChangedCallback)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        super.onDetachedFromRecyclerView(recyclerView)
        items.removeOnListChangedCallback(dataListChangedCallback)
    }

    fun getData() = items

    override fun getItemCount() = if (items.isEmpty()) 0 else items.size

    abstract fun getLayoutResId(): Int

    abstract fun onBindItem(binding: B?, bean: M, position: Int)

    /**
     * 额外监听数据变化，这样就可以直接更新数据，
     * 而不用每次都调用notifyDataSetChanged()等方式更新数据
     *
     *
     * 我只对插入和移除做了监听处理，其他方式没有处理
     * 小伙伴可以根据自己的具体需要做额外处理
     */
    inner class ListChangedCallback : ObservableList.OnListChangedCallback<ObservableArrayList<*>>() {
        override fun onChanged(newItems: ObservableArrayList<*>) {
            notifyDataSetChanged()
        }

        override fun onItemRangeChanged(newItems: ObservableArrayList<*>, positionStart: Int, itemCount: Int) {
            notifyItemRangeChanged(positionStart, itemCount ,"")
        }

        override fun onItemRangeInserted(newItems: ObservableArrayList<*>, positionStart: Int, itemCount: Int) {
            notifyItemRangeInserted(positionStart, itemCount)
        }

        override fun onItemRangeMoved(newItems: ObservableArrayList<*>, fromPosition: Int, toPosition: Int, itemCount: Int) {
            if (itemCount == 1) {
                notifyItemMoved(fromPosition, toPosition)
            } else {
                notifyDataSetChanged()
            }
        }

        override fun onItemRangeRemoved(newItems: ObservableArrayList<*>, positionStart: Int, itemCount: Int) {
            notifyItemRangeRemoved(positionStart, itemCount)
        }
    }
}